using System.Net;

namespace SmartBoard.Core.Networking
{
    /// <summary>
    /// Socket client host.
    /// </summary>
    public class SocketClient : BaseSocketConnectionHost
    {
        #region Constructor

        public SocketClient(CallbackThreadType callbackThreadType, ISocketService socketService)
            : base(HostType.Client, callbackThreadType, socketService, DelimiterType.None, null, 2048, 2048, 0, 0)
        { }

        public SocketClient(CallbackThreadType callbackThreadType, ISocketService socketService, DelimiterType delimiterType, byte[] delimiter)
            : base(HostType.Client, callbackThreadType, socketService, delimiterType, delimiter, 2048, 2048, 0, 0)
        { }

        public SocketClient(CallbackThreadType callbackThreadType, ISocketService socketService, DelimiterType delimiterType, byte[] delimiter, int socketBufferSize, int messageBufferSize)
            : base(HostType.Client, callbackThreadType, socketService, delimiterType, delimiter, socketBufferSize, messageBufferSize, 0, 0)
        { }

        public SocketClient(CallbackThreadType callbackThreadType, ISocketService socketService, DelimiterType delimiterType, byte[] delimiter, int socketBufferSize, int messageBufferSize, int idleCheckInterval, int idleTimeOutValue)
            : base(HostType.Client, callbackThreadType, socketService, delimiterType, delimiter, socketBufferSize, messageBufferSize, idleCheckInterval, idleTimeOutValue)
        { }
        #endregion

        #region Public Methods

        #region Overrides

        public override void Stop()
        {
            if (!IsDisposed)
            {
                StopConnections();
                StopCreators();
            }
            base.Stop();
        }
        #endregion

        public SocketConnector AddConnector(string name, IPEndPoint remoteEndPoint)
        {
            return AddConnector(name, remoteEndPoint, null, EncryptionType.None, CompressionType.None, null, 0, 0, new IPEndPoint(IPAddress.Any, 0));
        }

        public SocketConnector AddConnector(string name, IPEndPoint remoteEndPoint, ProxyInfo proxyData)
        {
            return AddConnector(name, remoteEndPoint, proxyData, EncryptionType.None, CompressionType.None, null, 0, 0, new IPEndPoint(IPAddress.Any, 0));
        }

        public SocketConnector AddConnector(string name, IPEndPoint remoteEndPoint, ProxyInfo proxyData, EncryptionType encryptionType, CompressionType compressionType, ICryptoService cryptoService)
        {
            return AddConnector(name, remoteEndPoint, proxyData, encryptionType, compressionType, cryptoService, 0, 0, new IPEndPoint(IPAddress.Any, 0));
        }

        public SocketConnector AddConnector(string name, IPEndPoint remoteEndPoint, ProxyInfo proxyData, EncryptionType encryptionType, CompressionType compressionType, ICryptoService cryptoService, int reconnectAttempts, int reconnectAttemptInterval)
        {
            return AddConnector(name, remoteEndPoint, proxyData, encryptionType, compressionType, cryptoService, reconnectAttempts, reconnectAttemptInterval, new IPEndPoint(IPAddress.Any, 0));
        }

        public SocketConnector AddConnector(string name, IPEndPoint remoteEndPoint, ProxyInfo proxyData, EncryptionType encryptionType, CompressionType compressionType, ICryptoService cryptoService, int reconnectAttempts, int reconnectAttemptInterval, IPEndPoint localEndPoint)
        {
            if (IsDisposed) return null;

            var result = new SocketConnector(this, name, remoteEndPoint, proxyData, encryptionType, compressionType, cryptoService, reconnectAttempts, reconnectAttemptInterval, localEndPoint);
            AddCreator(result);
            return result;
        }
        #endregion

        #region Internal Method Overrides

        internal override void BeginReconnect(ClientSocketConnection connection)
        {
            if (IsDisposed) return;
            if (connection == null) return;

            var connector = (SocketConnector)connection.Creator;
            if (connector == null) return;
            connector.ReconnectConnection(true, null);
        }

        internal override void BeginSendToAll(ServerSocketConnection connection, byte[] buffer, bool includeMe) 
        { }

        internal override void BeginSendTo(BaseSocketConnection connectionTo, byte[] buffer) 
        { }
        #endregion
    }
}